home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / checklpt.arc / FOPEN1.C < prev    next >
Encoding:
C/C++ Source or Header  |  1987-04-24  |  14.6 KB  |  326 lines

  1. /*    If the filename's path does not start with a back slash and it does, */
  2. /* not specify a drive, fopene_program looks first at the filename itself, */
  3. /* then appends it to any paths specified in a PATH-like environment       */
  4. /* variable which has the same name as the filename's extension, then      */
  5. /* appends it to any paths in the PATH enviroment variable.  Under DOS 3   */
  6. /* or later, it finally appends it to the calling program's drive and      */
  7. /* path.                                                                   */
  8. /*    fopene_program puts the actual drive, path and file name opened in   */
  9. /* full_filename_opened, which is available to the calling program.  If    */
  10. /* it runs into a system problem which prevents it from determining the    */
  11. /* drive and path, it uses the dummy "?:\?\", then the file name.          */
  12. /*                                                                         */
  13. /*    I compiled fopen1 for use with Lattice C, Version 3.  Some of its    */
  14. /* features which may not be portable are:                                 */
  15. /*    fopene is a Lattice 3 variant version of fopen which automatically   */
  16. /* searches the environment as described above.                            */
  17. /*   Lattice function getdsk returns 0 if the default drive is A:,         */
  18. /* 1 if it is B:, etc.                                                     */
  19. /*    Lattice function getcd takes a drive number as its first argument,   */
  20. /* with 0 for the default drive, 1 for A:, etc.  It returns the current    */
  21. /* directory in the variable pointed at by its second argument.  The       */
  22. /* current directory does not include either the drive letter or the       */
  23. /* trailing back-slash.  In particular, it returns an empty string for     */
  24. /* the root directory.                                                     */
  25. /*    dfind is a Lattice implementation of the DOS function which returns  */
  26. /* the directory entry which matches the input file name.  Sets the DOS    */
  27. /* information in a structure which has a type FILEINFO, and it returns    */
  28. /* 0 if it can make a match, -1 otherwise.                                 */
  29. /*    getenv(name) is a Lattice C function which returns a pointer to the  */
  30. /* information following the = sign in the DOS environment string of the   */
  31. /* form NAME=information.                                                  */
  32. /*    strupr converts a string to upper case.                              */
  33. /*    _DOS is a Lattice C system variable which contains the DOS major     */
  34. /* version.                                                                */
  35. /*    stcgfn is a Lattice expressions which get a file name path to a      */
  36. /* string variable.  The path does not have a trailing "\"                 */
  37. /*                                                                         */
  38. /*    Full identifiers in this program conform to the proposed ANSI        */
  39. /* standard of at most 31 significant characters, and they are different   */
  40. /* within the first 8 characters.  Lattice C includes a -n compiler        */
  41. /* switch which changes the number of significant characters in            */
  42. /* identifiers from 8 to 39.  While this program works without it, I       */
  43. /* designed them to use it.                                                */
  44. /*                                                                         */
  45. /* Lew Paper                                                               */
  46. /* 4/18/87                                                                 */
  47. /***************************************************************************/
  48.  
  49. #include <stdio.h>
  50. #include <string.h>
  51. #include <dos.h>
  52. #include <stdlib.h>
  53.  
  54. #define COPY_TO_WORK(STRING) (void) strcpy(working_path_and_name, STRING)
  55. #define ADD_TO_WORK(STRING) (void) strcat(working_path_and_name, STRING)
  56. #define ADD_TO_FULL(STRING) (void) strcat(full_filename_opened, STRING)
  57.  
  58. extern char _DOS;                   /* Lattice system variable.  DOS major */
  59.                                     /* version number                      */
  60.  
  61. char full_filename_opened[67] = "";    /* d:[path]\name.  Can be accessed  */
  62.                                        /* as an extern string in a calling */
  63.                                        /* program.                         */
  64.  
  65. static char upper_name[64];            /* Upper case of name               */
  66.  
  67. static char working_path_and_name[67]; /* Path and name without defaults   */
  68.  
  69.  
  70. /* Takes a string which represents a full directory, path, filename and    */
  71. /* extension for a file and removes all "." and ".." path components and   */
  72. /* effects.                                                                */
  73.  
  74. static int strip_dots()
  75.  
  76. {
  77.    char *pstart;                       /* Start of this subdirectory in    */
  78.                                        /* path                             */
  79.    char *plast;                        /* Previous subdirectory in path    */
  80.    char *p;
  81.  
  82.    plast = &full_filename_opened[3];   /* Address of first character after */
  83.                                        /* opening backslash                */
  84.    if (!(pstart = strchr(plast, '\\')))
  85.                                        /* True if in a subdirectory of     */
  86.                                        /* path.  False if in file name     */
  87.       return 0;
  88.  
  89.    ++pstart;                           /* Address of first character after */
  90.                                        /* backslash                        */
  91.    while (p = strchr(pstart, '\\'))    /* True if in a subdirectory of     */
  92.                                        /* path.  False if in file name     */
  93.    {
  94.       if (*pstart == '.')              /* Possible strip                   */
  95.       {
  96.          switch (p - pstart)
  97.          {
  98.             case 1:                    /* Must be .                        */
  99.                (void) strcpy(pstart, p + 1);
  100.                                        /* Get rid of this component        */
  101.                return 1;
  102.                /*lint -unreachable */
  103.                break;                  /* Defensive programming            */
  104.             case 2:
  105.                if (*(pstart + 1) == '.')
  106.                                        /* ..                               */
  107.                {
  108.                   (void) strcpy(plast, p + 1);
  109.                                        /* Get rid of this component and    */
  110.                                        /* the last one too                 */
  111.                   return 1;
  112.                }
  113.                break;
  114.             default:
  115.                break;
  116.          }
  117.       }
  118.  
  119.       plast = pstart;
  120.       pstart = p + 1;                  /* Address of first character after */
  121.                                        /* backslash                        */
  122.    }
  123.  
  124.    return 0;
  125.  
  126. }
  127.  
  128.  
  129. FILE *fopene_program(name, mode, argv0)
  130.    char *name;                         /* File name to be opened           */
  131.    char *mode;                         /* Mode to open in.  Probably only  */
  132.                                        /* makes sense as "r?" or "a?".     */
  133.    char *argv0;                        /* The value in argv[0] from        */
  134.                                        /* For DOS 3 or later, the calling  */
  135.                                        /* program.  For earlier versions,  */
  136.                                        /* a null string.                   */
  137.  
  138. {
  139.    int relative;                       /* 1 if OK to test paths            */
  140.    char *env_path;                     /* Pointer to environment PATH      */
  141.                                        /* string                           */
  142.    struct FILEINFO info;               /* For dfind()                      */
  143.    int not_found;                      /* Result of dfind()                */
  144.    char default_path[64];
  145.    FILE *fp;
  146.    char *p;
  147.    unsigned n;
  148.  
  149.    /* Convert name to upper case                                           */
  150.    (void) strcpy(upper_name, name);
  151.    (void) strupr(upper_name);
  152.  
  153.    if (fp = fopene(upper_name, mode, working_path_and_name))
  154.    {
  155. #ifdef DEBUG
  156.       fprintf(stderr, "fopene opened file %s and \n", name);
  157.       fprintf(stderr, "set working_path_and_name to \"%s\"\n",
  158.               working_path_and_name);
  159. #endif                                 /* #ifdef DEBUG                     */
  160.  
  161.       if (working_path_and_name[0])    /* fopene puts path in              */
  162.                                        /* working_path_and_name if it      */
  163.                                        /* finds the file in the path       */
  164.                                        /* defined by the filename          */
  165.                                        /* extension. If it finds the file  */
  166.                                        /* in the default directory, it     */
  167.                                        /* sets working_path_and_name to    */
  168.                                        /* "".  If it finds the file in the */
  169.                                        /* environment PATH, it does one or */
  170.                                        /* the other according to a rule    */
  171.                                        /* which I have yet to figure out.  */
  172.       {
  173.          (void) strupr(working_path_and_name);
  174.          if (*(working_path_and_name + strlen(working_path_and_name) - 1)
  175.               != '\\')
  176.             ADD_TO_WORK("\\");
  177.          ADD_TO_WORK(upper_name);
  178.       }
  179.       else
  180.       {
  181.          relative = ((upper_name[0] != '\\') && (upper_name[1] != ':'));
  182.          if (!relative)                /* Must have opened without a path  */
  183.             COPY_TO_WORK(upper_name);
  184.          else
  185.          {
  186. #ifdef DEBUG
  187.             fprintf(stderr, "Check directory for %s \n", upper_name);
  188. #endif                                 /* #ifdef DEBUG                     */
  189.             if (!dfind(&info, upper_name, 0))
  190.                                        /* File opened by default path      */
  191.                COPY_TO_WORK(upper_name);
  192.  
  193.             /* Check which part of PATH opened the file                    */
  194.             else
  195.             {
  196.                if (env_path = getenv("PATH"))
  197.                do
  198.                {
  199.                   if (p = strchr(env_path, ';'))
  200.                      n = p - env_path;
  201.                   else
  202.                      n = (unsigned) strlen(env_path);
  203.                   (void) strncpy(working_path_and_name, env_path, n);
  204.                   working_path_and_name[n] = (char) 0;
  205.                   if (*(working_path_and_name + n - 1) != '\\')
  206.                         ADD_TO_WORK("\\");
  207.                   ADD_TO_WORK(upper_name);
  208.                   env_path = p + 1;    /* Junk, but not used, if p = NULL  */
  209. #ifdef DEBUG
  210.                   fprintf(stderr, "Check directory for %s ",
  211.                           working_path_and_name);
  212.                   fputs("from PATH\n", stderr);
  213. #endif                                 /* #ifdef DEBUG                     */
  214.                   not_found = dfind(&info, working_path_and_name, 0);
  215.                } while (not_found && p);
  216.       
  217.                if (not_found)
  218.                {
  219.                   fputs("Program error in function fopene_program.\n", stderr);
  220.                   fprintf(stderr, "Could not find file %s ", name);
  221.                   fputs("in the environment PATH\n", stderr);
  222.                   fprintf(stderr, "\"%s\"\n\n", getenv("PATH"));
  223.                   COPY_TO_WORK("?:\\?\\");
  224.                }
  225.             }
  226.          }
  227.       }
  228.    }
  229.    else                             /* Couldn't open the file with         */
  230.                                     /* environment paths                   */
  231.    {
  232. #ifdef DEBUG
  233.       fprintf(stderr, "fopene couldn't open file %s\n", name);
  234. #endif                                 /* #ifdef DEBUG                     */
  235.  
  236.       if (_DOS >= 3 && relative)
  237.       {
  238.          /* Try to open with path of calling program                       */
  239.          (void) stcgfp(working_path_and_name, argv0);
  240.          (void) strupr(working_path_and_name);
  241.          ADD_TO_WORK("\\");
  242.          ADD_TO_WORK(upper_name);
  243. #ifdef DEBUG
  244.          fprintf(stderr, "Try to open %s from argv0\n",
  245.                           working_path_and_name);
  246. #endif                                 /* #ifdef DEBUG                     */
  247.          fp = fopen(working_path_and_name, mode);
  248.       }
  249.    }
  250.  
  251.    /* Set full_filename_opened                                             */
  252.    if (fp)
  253.    {
  254.       p = working_path_and_name;
  255.       if (working_path_and_name[1] == ':')
  256.                                        /* Drive specified                  */
  257.       {
  258.          (void) strncpy(full_filename_opened, working_path_and_name, 2);
  259.          p += 2;
  260.       }
  261.       else                             /* Use default drive                */
  262.       {
  263.          full_filename_opened[0] = getdsk() + 'A';
  264.          full_filename_opened[1] = ':';
  265.       }
  266.       full_filename_opened[2] = (char) 0;
  267.  
  268.       if (*p != '\\')                  /* Append to default path           */
  269.       {
  270.          ADD_TO_FULL("\\");
  271.          (void) getcd(full_filename_opened[0] - 'A' + 1, default_path);
  272.          if (default_path[0])
  273.          {
  274.             ADD_TO_FULL(default_path);
  275.             ADD_TO_FULL("\\");
  276.             ADD_TO_FULL(p);
  277.          }
  278.       }
  279.       else                             /* Don't use default path           */
  280.          ADD_TO_FULL(p);
  281.    }
  282.    else
  283.       full_filename_opened[0] = (char) 0;
  284.  
  285.    /* Strip full_filename_opened of "." and ".." components                */
  286.       while (strip_dots())             /* Strip one component each cycle   */
  287.                                        /* strip_dots returns 1 if it       */
  288.                                        /* strips a component, 0 otherwise  */
  289.          ;
  290.  
  291.    return fp;
  292. }
  293.  
  294. #ifdef DEBUG
  295.  
  296. /* Test program for fopene_program                                         */
  297.  
  298. void main(argc, argv)
  299.    int argc;
  300.    char *argv[];
  301.  
  302. {
  303.    FILE *fp;
  304.  
  305.    if (argc < 2)
  306.    {
  307.       fputs("Usage: fopen1 <filename>\n", stderr);
  308.       fputs("     where filename is [d][path]name.ext to be opened", stderr);
  309.       fputs(" with no wild cards \n\n", stderr);
  310.       exit(1);
  311.    }
  312.  
  313.    if (fp = fopene_program(argv[1], "r", argv[0]))
  314.    {
  315.       fprintf(stderr, "Opened file %s\n", argv[1]);
  316.       if (fclose(fp))
  317.          fputs("Program error closing it\n", stderr);
  318.    }
  319.    else
  320.       fprintf(stderr, "Unable to open file %s\n", argv[1]);
  321.    fprintf(stderr, "full_filename_opened = \"%s\"\n\n",
  322.            full_filename_opened);
  323.    exit(0);
  324. }
  325. #endif                                 /* ifdef DEBUG                      */
  326.